package top.wilsonlv.jaguar.cloud.upms.controller;

import com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;
import com.alibaba.nacos.api.exception.NacosException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.annotations.ApiIgnore;
import top.wilsonlv.jaguar.basecrud.BaseController;
import top.wilsonlv.jaguar.cloud.upms.controller.dto.OAuthClientCreateDTO;
import top.wilsonlv.jaguar.cloud.upms.controller.dto.OAuthClientModifyDTO;
import top.wilsonlv.jaguar.cloud.upms.controller.vo.OAuthClientVO;
import top.wilsonlv.jaguar.cloud.upms.entity.OAuthClient;
import top.wilsonlv.jaguar.cloud.upms.mapper.OAuthClientMapper;
import top.wilsonlv.jaguar.cloud.upms.service.OAuthClientService;
import top.wilsonlv.jaguar.commons.mybatisplus.extension.JaguarLambdaQueryWrapper;
import top.wilsonlv.jaguar.commons.web.response.JsonResult;
import top.wilsonlv.jaguar.oauth2.resourceserver.api.OAuthResourceServiceApi;

import javax.validation.Valid;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author lvws
 * @since 2021-07-27
 */
@Validated
@RestController
@RequestMapping("/oauthClient")
@Api(tags = "oauth2客户端管理")
@RequiredArgsConstructor
public class OAuthClientController extends BaseController<OAuthClient, OAuthClientMapper, OAuthClientService> {

    private final RestTemplate restTemplate;

    private final NacosServiceDiscovery serviceDiscovery;


    @ApiOperation(value = "分页查询oauth2客户端")
    @PreAuthorize("hasAuthority('oauth2客户端管理')")
    @GetMapping(value = "/page")
    public JsonResult<Page<OAuthClientVO>> page(
            @ApiIgnore Page<OAuthClient> page,
            @ApiParam(value = "模糊用户信息") @RequestParam(required = false) String fuzzyClientId) {

        LambdaQueryWrapper<OAuthClient> wrapper = JaguarLambdaQueryWrapper.<OAuthClient>newInstance()
                .like(OAuthClient::getClientId, fuzzyClientId);
        return success(service.queryOauthClient(page, wrapper));
    }

    @ApiOperation(value = "oauth2客户端详情")
    @PreAuthorize("hasAuthority('oauth2客户端管理')")
    @GetMapping(value = "/{id}")
    public JsonResult<OAuthClientVO> detail(@PathVariable Long id) {
        return success(service.getDetail(id));
    }

    @ApiOperation(value = "新增oauth2客户端")
    @PreAuthorize("hasAuthority('oauth2客户端管理')")
    @PostMapping
    public JsonResult<String> create(@RequestBody @Valid OAuthClientCreateDTO oauthClient) {
        return success(service.create(oauthClient));
    }

    @ApiOperation(value = "修改oauth2客户端")
    @PreAuthorize("hasAuthority('oauth2客户端管理')")
    @PutMapping
    public JsonResult<Void> modify(@RequestBody @Valid OAuthClientModifyDTO oauthClient) {
        service.modify(oauthClient);
        return success();
    }

    @ApiOperation(value = "重置密钥")
    @PreAuthorize("hasAuthority('oauth2客户端管理')")
    @PostMapping("/resetSecret")
    public JsonResult<String> resetSecret(@RequestParam Long id) {
        return success(service.resetSecret(id));
    }

    @ApiOperation(value = "删除oauth2客户端")
    @PreAuthorize("hasAuthority('oauth2客户端管理')")
    @DeleteMapping(value = "/{id}")
    public JsonResult<Void> del(@PathVariable Long id) {
        service.checkAndDelete(id);
        return success();
    }

    @ApiOperation(value = "查询oauth2 scope")
    @PreAuthorize("hasAuthority('oauth2客户端管理')")
    @GetMapping(value = "/scopes")
    public JsonResult<Map<String, String[]>> scopes(@RequestParam(required = false) Set<String> serverIds)
            throws NacosException, URISyntaxException {

        if (CollectionUtils.isEmpty(serverIds)) {
            return JsonResult.success(Collections.emptyMap());
        }

        ParameterizedTypeReference<JsonResult<String[]>> typeReference =
                new ParameterizedTypeReference<JsonResult<String[]>>() {
                };

        Map<String, String[]> scopes = new HashMap<>();
        for (String serviceId : serviceDiscovery.getServices()) {
            if (!serverIds.contains(serviceId)) {
                continue;
            }

            String httpUrl = "http://" + serviceId + OAuthResourceServiceApi.PATH_RESOURCE_SERVER_SCOPES;
            RequestEntity<?> requestEntity = new RequestEntity<>(null, HttpMethod.GET, new URI(httpUrl));

            ResponseEntity<JsonResult<String[]>> entity = restTemplate.exchange(requestEntity, typeReference);
            if (entity.getStatusCode() == HttpStatus.OK && entity.getBody() != null
                    && entity.getBody().getResultCode() == HttpStatus.OK.value()) {
                scopes.put(serviceId, entity.getBody().getData());
            }
        }
        return success(scopes);
    }
}